package com.corpgovernment.common.apollo;

import com.alibaba.fastjson.JSONObject;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.constant.CommonConst;
import com.corpgovernment.common.dto.SupplierConfigDTO;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.holder.TenantContextHolder;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.corpgovernment.common.utils.TenantUtils;
import com.ctrip.corp.obt.generic.apollo.TenantConfigService;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Supplier;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName: CommonApollo
 * @description: 阿波罗公共配置
 * @author: ezchen
 * @date: Created in 17:07 2020/7/7
 * @Version: 1.0
 **/
@Component
@Data
@Slf4j
public class CommonApollo {

    @Value("${spring.redis.cluster.nodes:}")
    private String cluster;
    @Value("${spring.redis.password:}")
    private String password;
    @Value("${spring.redis.host:}")
    private String redisHost;
    @Value("${spring.redis.port:}")
    private String redisPort;
    /**
     * 携程的supplierCodes
     */
    @Value("${ctrip.supplierCodeList:ctrip,ctrip2}")
    private String ctripSupplierCodeList;
    /**
     * 携程的supplierCode
     */
    @Value("${supplierCodeConst.ctrip:ctrip}")
    private String supplierCodeConstCtrip;
    /**
     * 供应商key 供服务商推送接口验签使用
     */
    @Value("${supplierUserKey:}")
    private String supplierUserKey;
    /**
     * 火车票服务商操作类型
     */
    @Value("${trainOperatorTypeConfig:}")
    private String trainOperatorType;
    /**
     * 机票服务商操作类型
     */
    @Value("${flightOperatorType:}")
    private String flightOperatorType;
    /**
     * 酒店服务商操作类型
     */
    @Value("${hotelOperatorType:}")
    private String hotelOperatorType;
    /**
     * 其他的操作类型
     */
    @Value("${otherOperatorType:}")
    private String otherOperatorType;
    /**
     * 支付相关
     */
    @Value("${paymentOperatorType:}")
    private String paymentOperatorType;

    /**
     * 控制前端轮询查机票超时时间
     */
    @Value("${queryFlightListTimeout:20000}")
    private Integer queryFlightListTimeout;
    /**
     * 平台这边客户对应code
     */
    @Value("${platformChannel:}")
    private String platformChannel;

    @Value("${pcadmin.host:}")
    private String pcAdminHost;
    @Value("${main.admin.url:}")
    private String mailAdminUrl;
    @Value("${mail.portal.url:}")
    private String mailPortalUrl;

    @Value("${pcbook.host:}")
    private String pcBookHost;

    @Value("${app.host:}")
    private String appHost;

    @Value("${portal.host:}")
    private String portalHost;

    @Value("${is.split.product.type:false}")
    private Boolean isSplitProductType;

    @Value("${rocketmq.consumer.namesrvAddr:f}")
    private String consumerNamesrvAddr;
    @Value("${rocketmq.consumer.consumeThreadMin:20}")
    private int consumeThreadMin;
    @Value("${rocketmq.consumer.consumeThreadMax:64}")
    private int consumeThreadMax;
    @Value("${rocketmq.consumer.consumeMessageBatchMaxSize:1}")
    private int consumeMessageBatchMaxSize;
    @Value("${rocketmq.consumer.accesskey:}")
    private String consumerAccessKey;
    @Value("${rocketmq.consumer.accesskey-secret:}")
    private String consumerAccessKeySecret;
    @Value("${rocketmq.producer.namesrvAddr:f}")
    private String producerNamesrvAddr;
    @Value("${rocketmq.producer.accesskey:}")
    private String producerAccessKey;
    @Value("${rocketmq.producer.accesskey-secret:}")
    private String producerAccessKeySecret;
    @Value("${rocketmq.producer.maxMessageSize:4}")
    private int maxMessageSize;
    /**
     * 消息发送超时时间，默认3秒
     */
    @Value("${rocketmq.producer.sendMsgTimeout:3}")
    private int sendMsgTimeout;
    /**
     * 消息发送失败重试次数，默认2次
     */
    @Value("${rocketmq.producer.retryTimesWhenSendFailed:2}")
    private int retryTimesWhenSendFailed;

    @Value("${has.contain.book.scope:true}")
    private boolean hasContainBookScope;

    @Value("${proxyUrl:}")
    private String proxyUrl;

    @Value("${proxyPort:}")
    private Integer proxyPort;

    @Value("${pushUrl:}")
    private String pushUrl;

    @Value("${ctripUrl:}")
    private String ctripUrl;

    @Value("${enabledCtripAccount:}")
    private Boolean enabledCtripAccount;

    @Value("${supplier.config:{}}")
    private String supplierConfig;

    @Value("${companyShortNameMap:}")
    private String companyShortNameMap;


    /**
     * 	{
     * 	    "ctrip":"url"
     * 	    "meiya":"url"
     * 	}
     * @return
     */
    public Map<String, SupplierConfigDTO> getSupplierConfig() {
        Map<String , SupplierConfigDTO> ret = new HashMap<>();
        JsonUtils.parseMap(getCommonProperty("supplier.config", "{}")).forEach(
                (supplier, config) -> {
                    ret.put(supplier, JsonUtils.parse(JsonUtils.toJsonString(config), SupplierConfigDTO.class));
                }
        );
        return ret;
    }

    /**
     * 发票类型
     *
     * @return
     */
    public List<Integer> getInvoiceType() {
        return Optional.ofNullable(getCommonProperty("invoiceType", ""))
                .filter(StringUtils::isNotBlank)
                .map(e -> e.split(","))
                .map(e -> Arrays.stream(e).map(Integer::valueOf).collect(Collectors.toList()))
                .orElse(Lists.newArrayList());
    }

    /**
     * 是否是携程供应商
     */
    public boolean isCtrip(String supplierCode) {
        return !StringUtils.isBlank(ctripSupplierCodeList) && ctripSupplierCodeList.contains(supplierCode);
    }

    public String getSystemModel() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("system_model", CommonConst.DEFAULT_SYSTEM_MODEL);
    }

    /**
     * 获取common 配置
     *
     * @param key
     * @param defaultVal
     * @return
     */
    public String getCommonProperty(String key, String defaultVal) {
        return this.getProperty(key, defaultVal, this::getCommonConfig);
    }

    /**
     * 获取 app 配置
     *
     * @param key
     * @param defaultVal
     * @return
     */
    public String getAppProperty(String key, String defaultVal) {
        return this.getProperty(key, defaultVal, this::getAppConfig);
    }

    /**
     * 获取阿波罗配置
     *
     * @param key
     * @param defaultVal
     * @return
     */
    public final String getProperty(String key, String defaultVal, Supplier<Config> supplier) {
        String systemModel = getSystemModel();
        String tenantId = TenantContextHolder.getTenantId();
        log.info("获取apollo配置，当前租户id:{}, key:{}，defaultVal:{}", tenantId, key, defaultVal);
        if (Objects.equals(CommonConst.DEFAULT_SYSTEM_MODEL, systemModel)) {
            if (StringUtils.isNotBlank(tenantId) && !Objects.equals(tenantId, CommonConst.DEFAULT_TENANT_ID)) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, String.format(CommonConst.SINGLE_SYSTEM_ERROR, tenantId));
            }
            // 当前为单租户模式
            return TenantUtils.replaceTenant(supplier.get().getProperty(key, defaultVal));
        } else {
            if (StringUtils.isBlank(tenantId)) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, CommonConst.MULTI_SYSTEM_ERROR);
            }
            if (Objects.equals(tenantId, CommonConst.DEFAULT_TENANT_ID)) {
                return TenantUtils.replaceTenant(supplier.get().getProperty(key, defaultVal));
            } else {
                return TenantUtils.replaceTenant(supplier.get().getProperty(key, defaultVal));
            }
        }
    }

    /**
     * 获取common config
     *
     * @return
     */
    public Config getCommonConfig() {
        String systemModel = getSystemModel();
        String tenantId = TenantContextHolder.getTenantId();
        if (Objects.equals(CommonConst.DEFAULT_SYSTEM_MODEL, systemModel) || Objects.equals(tenantId, CommonConst.DEFAULT_TENANT_ID)) {
            // 当前为单租户模式
            log.info("单租户模式common");
            return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON);
        } else {
            log.info("多租户模式common，tenantId:{}", tenantId);
            return TenantConfigService.getConfig(tenantId, CommonConst.NAMESPACE_COMMON);
        }
    }

    /**
     * 获取 app config
     *
     * @return
     */
    public Config getAppConfig() {
        String systemModel = getSystemModel();
        String tenantId = TenantContextHolder.getTenantId();
        if (Objects.equals(CommonConst.DEFAULT_SYSTEM_MODEL, systemModel) || Objects.equals(tenantId, CommonConst.DEFAULT_TENANT_ID)) {
            // 当前为单租户模式
            log.info("单租户模式application");
            return ConfigService.getConfig(CommonConst.NAMESPACE_APPLICATION);
        } else {
            log.info("多租户模式application，tenantId:{}", tenantId);
            return TenantConfigService.getConfig(tenantId, CommonConst.NAMESPACE_APPLICATION);
        }
    }

    public Map<String, String> getUrlTenantMap() {
        String urlTenantMapStr = getCommonProperty("url_tenant_map", "");
        return (Map<String, String>) JSONObject.parseObject(urlTenantMapStr, Map.class);
    }

    public String getPushUrl() {
        return getCommonProperty("pushUrl", "");
    }

    public String getCtripUrl() {
        return getCommonProperty("ctripUrl", "");
    }

    public boolean getEnabledCtripAccount() {
        return Optional.ofNullable(getCommonProperty("enabledCtripAccount", "")).map(Boolean::valueOf).orElse(false);
    }

    public String getTenantInfo() {
        return getCommonProperty("tenant_info", "");
    }

    /**
     *
     */
    public Boolean getHasContainBookScope() {
        return Boolean.valueOf(getCommonProperty("has.contain.book.scope", "true"));
    }

    /**
     *
     */
    public Boolean getIsSplitProductType() {
        return Boolean.valueOf(getCommonProperty("is.split.product.type", "false"));
    }

    public Map<String, List<String>> getTenantAndCorpRelation() {
        return (Map<String, List<String>>) JSONObject.parseObject(getCommonProperty("tenant.and.corp.relation", ""), Map.class);
    }

    /**
     * producer access key
     *
     * @return
     */
    public String getProducerNamesrvAddr() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.producer.namesrvAddr", "f");
    }

    /**
     * producer access key
     *
     * @return
     */
    public String getProducerAccessKey() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.producer.accesskey", "");
    }

    /**
     * producer secret
     *
     * @return
     */
    public String getProducerAccessKeySecret() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.producer.accesskey-secret", "");
    }

    public String getProducerNamespace() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.producer.namespace", "");
    }

    /**
     * consumer access key
     *
     * @return
     */
    public String getConsumerNamesrvAddr() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.consumer.namesrvAddr", "f");
    }

    /**
     * consumer access key
     *
     * @return
     */
    public String getConsumerAccessKey() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.consumer.accesskey", "");
    }

    /**
     * consumer secret
     *
     * @return
     */
    public String getConsumerAccessKeySecret() {
        return ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("rocketmq.consumer.accesskey-secret", "");
    }

    /**
     * 获取租户列表
     *
     * @return
     */
    public List<String> getTenantList() {
        return Arrays.asList(ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("apollo.multitenantmeta.tenant", "").split(","));
    }

    /**
     * 获取白名单url列表
     *
     * @return
     */
    public List<String> getDomainWhiteList() {
        String domains = ConfigService.getConfig(CommonConst.NAMESPACE_COMMON).getProperty("third.white.url", "");
        return Arrays.asList(domains.split(","));
    }

    /**
     * druidClassName
     *
     * @return
     */
    public String getDriverClassName() {
        return getCommonProperty("spring.druid.druidClassName", null);
    }

    /**
     * url
     *
     * @return
     */
    public String getDatabaseUrl() {
        return getCommonProperty("spring.druid.url", null);
    }

    /**
     * password
     *
     * @return
     */
    public String getDatabasePassword() {
        return getCommonProperty("spring.druid.password", null);
    }

    /**
     * username
     *
     * @return
     */
    public String getDatabaseUsername() {
        return getCommonProperty("spring.druid.username", null);
    }


    /**
     * initialSize
     *
     * @return
     */
    public Integer getDatabaseInitialSize() {
        return Integer.valueOf(getCommonProperty("spring.druid.initialSize", "10"));
    }

    /**
     * maxActive
     *
     * @return
     */
    public Integer getDatabaseMaxActive() {
        return Integer.valueOf(getCommonProperty("spring.druid.maxActive", "30"));
    }

    /**
     * minIdle
     *
     * @return
     */
    public Integer getDatabaseMinIdle() {
        return Integer.valueOf(getCommonProperty("spring.druid.minIdle", "20"));
    }

    /**
     * maxWait
     *
     * @return
     */
    public Integer getDatabaseMaxWait() {
        return Integer.valueOf(getCommonProperty("spring.druid.maxWait", "30000"));
    }

    public String getProxyUrl() {
        return getCommonProperty("proxyUrl", "");
    }

    public Integer getProxyPort() {
        return Integer.valueOf(getCommonProperty("proxyPort", ""));
    }

   /* public Integer getMaxMessageSize() {
        return Integer.parseInt(getCommonProperty("rocketmq.producer.maxMessageSize", ""));
    }*/


    @Value("${airportTransferOperatorType:}")
    private String airportTransferOperatorType;

    @Value("${trainTransferOperatorType:}")
    private String trainTransferOperatorType;

    public String getPortalHost(){
        return getCommonProperty("portal.host", "");
    }

    public String getPcAdminHost(){
        return getCommonProperty("pcadmin.host", "");
    }

    public String getMailAdminUrl(){
        return getCommonProperty("main.admin.url", "");
    }

    public String getMailPortalUrl(){
        return getCommonProperty("mail.portal.url", "");
    }

    public String getPcBookHost(){
        return getCommonProperty("pcbook.host", "");
    }

    public String getAppHost(){
        return getCommonProperty("app.host", "");
    }

    /**
     * 判断一个值是否存在配置项里面(判断前提是用|分割开来) 当配置为“ALL”时则表示全部符合
     *
     * @param key 配置的key
     * @param itemValue 需要判断的值
     */
    public boolean existsItemOrAll(String key, String itemValue) {
        HashSet<String> itemSet = Sets.newHashSet(getAppProperty(key, "").split("\\|"));
        if (itemSet.size() == 1 && itemSet.stream().allMatch("ALL"::equals)) {
            return true;
        }
        return itemSet.contains(itemValue);
    }

    /** 公司简称配置 */
    public String getCompanyShortName() {
        return getCommonProperty("companyShortNameMap", "");
    }

}
